package com.study.business.aspect;

import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;

@Component
@Slf4j
@Aspect
public class RestLogAspect {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Pointcut("execution(* com.study.business.*.controller.*.*(..))")
    private void logPointcut() {

    }


    @Around("logPointcut()")
    public Object logAround(ProceedingJoinPoint point) {
        //获取参数
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();

        HttpServletRequest request = requestAttributes.getRequest();

        Map<String, Object> result = new LinkedHashMap<>();

        String remoteAddress = request.getRemoteAddr();
        int remotePort = request.getRemotePort();
        result.put("remoteAddress", remoteAddress + ":" + remotePort);

        String requestURI = request.getRequestURI();
        result.put("requestUrl", StringUtils.isEmpty(requestURI) ? "" : requestURI);

        String method = request.getMethod();
        String methodName = point.getSignature().getName();
        result.put("method", method + "#" + methodName);

        String queryString = request.getQueryString();
        result.put("params", queryString);

        if (!"GET".equalsIgnoreCase(method)) {

            Object[] args = point.getArgs();
            result.put("body", Arrays.toString(args));
        }
        //执行方法前
        Object returnVal = null;
        //执行方法
        long start = System.currentTimeMillis();
        try {

            returnVal = point.proceed();
            //执行方法后
        } catch (Throwable e) {
            log.error("执行方法:{},出现异常:", methodName, e);
        }
        result.put("result", returnVal);
        result.put("cost", System.currentTimeMillis() - start);
        result.put("requestDate", new Date());
        log.info(JSONUtil.toJsonPrettyStr(result));
        rabbitTemplate.convertAndSend("storage_event", "event.study", JSONUtil.toJsonStr(result));
        return returnVal;
    }
}
